2B: More on Vector

Readings

From R Coding Basics: An Introduction to the Basics of Coding in R by Dr. Gaston Sanchez:

Topics

  • Implicit and explicit coercion

  • Vectorization and recycling

  • Working with logical vectors

  • Subsetting: numeric and logical indexing

  • Useful functions for vectors

Implicit coercion

  • Broadly speaking, implicit coercion is how R decides what type the output should be when combining or performing operations on different atomic types.

  • Implicit coercion is most commonly found in calculations with logical values and in vector creation using the combine c() function.

Calculations with logical values

  • Logical values are automatically coerced to numeric when used in calculations.
# TRUE becomes 1 so 1 + 5 = 6
TRUE + 5     
[1] 6
# FALSE becomes 0 so 0 + 5 = 5
FALSE + 5    
[1] 5
# 1 + 0 + 1 = 2
v <- c(TRUE, FALSE, TRUE)
sum(v)    
[1] 2

💻 Hands-On

Guess the output in the following R code. Try the code to confirm your guess.

TRUE * 2

FALSE * 2

v1 <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE)
sum(v1)

v2 <- c(F, T, F, F, T, F, T)
sum(v2)
# TRUE becomes 1 so 1 * 2 = 2
TRUE * 2
[1] 2
# FALSE becomes 0 so 0 * 2 = 0
FALSE * 2
[1] 0
# 1 + 1 + 0 + 0 + 1 + 0 + 0 = 3
v1 <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE)
sum(v1)
[1] 3
# 0 + 1 + 0 + 0 + 1 + 0 + 1 = 3
v2 <- c(F, T, F, F, T, F, T)
sum(v2)
[1] 3

Combining values with c()

  • Implicit coercion also occurs when we combine different atomic types into a single vector.

  • In this case, all elements are converted to the most complex type (character).

\[ \text{Character} \, > \, \text{Double} \, > \, \text{Integer} \, > \, \text{Logical} \]

# integer > logical
c(4L, TRUE, TRUE, FALSE)                   
[1] 4 1 1 0
# double > integer > logical
c(7.3, 4L, TRUE, TRUE, FALSE)              
[1] 7.3 4.0 1.0 1.0 0.0
# character > double > integer > logical
c("eagles", 7.3, 4L, TRUE, TRUE, FALSE)    
[1] "eagles" "7.3"    "4"      "TRUE"   "TRUE"   "FALSE" 

💻 Hands-On

Guess the output in the following R code. Try the code to confirm your guess.

v1 <- c(TRUE, 3.5, FALSE, 1L)
sum(v1)

v2 <- c(FALSE, TRUE, 2, 3, "4", 5L)
sum(v2)
# Coercion gives c(1.0, 3.5, 0.0, 1.0)
v1 <- c(TRUE, 3.5, FALSE, 1L)
sum(v1)
[1] 5.5
# Coercion gives c("FALSE", "TRUE", "2", "3", "4", "5") so sum() gives an error
v2 <- c(FALSE, TRUE, 2, 3, "4", 5L)
sum(v2)
Error in sum(v2): invalid 'type' (character) of argument

Explicit coercion

  • Explicit coercion directly forces one atomic type to become another.
as.logical()      # to logical type

as.integer()      # to integer type
as.double()       # to double type
as.numeric()      # to numeric type

as.character()    # to character type

Vectorization

  • In R, vectorization means when we apply a function or operation on a vector, it will be done element by element automatically.

  • This means we do not need to loop through the vector.

#       x:      4        8         25         49
# sqrt(x): sqrt(4)  sqrt(8)   sqrt(25)   sqrt(49)
#  output:      2        3          5          7

x <- c(4, 9, 25, 49)
sqrt(x)
[1] 2 3 5 7
  • Vectorization also implies that an operation on two vectors will be done in an element-wise manner.
#      x:  1  2  3  4
#          +  +  +  +
#      y:  3  5  6  2
# output:  4  7  9  6

x <- c(1, 2, 3, 4)
y <- c(3, 5, 6, 2)
x + y
[1] 4 7 9 6

💻 Hands-On

Verify the properties of vectorization with the following code

x <- c(1, 2, 3, 4)
y <- c(3, 5, 6, 2)

x - y

x * y

y / x

log(y)

sin(x)

Due to vectorization, R will perform operations on corresponding elements.

x <- c(1, 2, 3, 4)
y <- c(3, 5, 6, 2)

See the following

x - y
[1] -2 -3 -3  2
x * y
[1]  3 10 18  8
y / x
[1] 3.0 2.5 2.0 0.5
log(y)
[1] 1.0986123 1.6094379 1.7917595 0.6931472
sin(x)
[1]  0.8414710  0.9092974  0.1411200 -0.7568025

Recycling

  • When performing operations on two vectors are different lengths, R will recycle the shorter vector to match the length of the longer one.
#      x: 1  2  3  4
#         *  *  *  *
#         2  2  2  2
# output: 2  4  6  8

x <- c(1, 2, 3, 4)
x * 2
[1] 2 4 6 8
  • Recycling can produce confusing results, so it is recommended that two vectors either have the same length or that one of them has length 1.

💻 Hands-On

Try the following R code and see what it returns. What do you think this sneaky code does?

# Please avoid!

x <- c(5, 3, 7, 4, 6, 8, 3)
y <- c(1, 2)
x + y

We will see the followling

x <- c(5, 3, 7, 4, 6, 8, 3)
y <- c(1, 2)
x + y
[1]  6  5  8  6  7 10  4

The shorter vector y recycles its elements to match the length of the longer vector x. The above is equivalent to

x <- c(5, 3, 7, 4, 6, 8, 3)
y <- c(1, 2, 1, 2, 1, 2, 1)
x + y
[1]  6  5  8  6  7 10  4

Working with logical vectors

  • Logical vectors are frequently used in data analysis to account for different conditions.
# logical vector
c(TRUE, FALSE, FALSE, TRUE, TRUE)
c(T, F, F, T, T)

Comparison operators

  • A logical vector can be created using comparison operators.
Logical Operator Description
< Less than
<= Less than or equal to
> Greater than
>= Greater than or equal to
== Exactly equal to
!= Not equal to
  • Consider the following vector
x <- c(-2, -1, 0, 1, 2, 3)
  • We have
# less than
x < 0     
[1]  TRUE  TRUE FALSE FALSE FALSE FALSE
# less than or equal to
x <= 0    
[1]  TRUE  TRUE  TRUE FALSE FALSE FALSE
# greater than
x > 0     
[1] FALSE FALSE FALSE  TRUE  TRUE  TRUE
# greater than or equal to
x >= 0    
[1] FALSE FALSE  TRUE  TRUE  TRUE  TRUE
# exactly equal to
x == 0    
[1] FALSE FALSE  TRUE FALSE FALSE FALSE
# not equal to
x != 0    
[1]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE

💻 Hands-On

Consider daily high temperatures in celsius over two weeks. Write R code to answer the following questions:

  • Which days had temperatures at least 30°C?

  • Which days had temperatures exactly equal to 19°C?

  • Which days had temperatures below 20°C?

  • Which days had temperatures greater than 25°C?

  • Which days had temperatures at most 22°C?

# Daily high temperatures over two weeks
temps <- c(
  Mon02 = 18, Tue03 = 21, Wed04 = 19, Thu05 = 25, Fri06 = 27, Sat07 = 30, Sun08 = 22, 
  Mon09 = 20, Tue10 = 16, Wed11 = 24, Thu12 = 28, Fri13 = 31, Sat14 = 29, Sun15 = 17
)

Here, we will create logical vectors and use TRUE values to tell which days satisfy the conditions. Note that the vector temps has names to make it easier to tell.

temps >= 30
Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14 
FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE 
Sun15 
FALSE 
temps == 19
Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14 
FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
Sun15 
FALSE 
temps < 20
Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14 
 TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE 
Sun15 
 TRUE 
temps > 25
Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14 
FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE 
Sun15 
FALSE 
temps <= 22
Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14 
 TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE 
Sun15 
 TRUE 

The sum() function

  • Applying the sum() function to a logical vector gives the number of TRUE values.

  • Recall that implicit coercion turns logical values to \(1\)’s and \(0\)’s.

# 1 + 0 + 0 + 1 + 1 
v <- c(TRUE, FALSE, FALSE, TRUE, TRUE)
sum(v)
[1] 3

💻 Hands-On

Consider the following vector

x <- c(-2, -1, 0, 1, 2, 3)

Try the following R code and see what it returns.

sum(x < 0)

sum(x <= 0)

sum(x > 0)

sum(x >= 0)

sum(x == 0)

sum(x != 0)
sum(x < 0)
[1] 2
sum(x <= 0)
[1] 3
sum(x > 0)
[1] 3
sum(x >= 0)
[1] 4
sum(x == 0)
[1] 1
sum(x != 0)
[1] 5

💻 Hands-On

Consider daily high temperatures in celsius over two weeks. Write R code to answer the following questions:

  • How many days had temperatures below 18°C?

  • How many days had temperatures greater than 26°C?

  • How many days had temperatures at most 21°C?

  • How many days had temperatures at least 28°C?

# Daily high temperatures over two weeks
temps <- c(
  Mon02 = 18, Tue03 = 21, Wed04 = 19, Thu05 = 25, Fri06 = 27, Sat07 = 30, Sun08 = 22, 
  Mon09 = 20, Tue10 = 16, Wed11 = 24, Thu12 = 28, Fri13 = 31, Sat14 = 29, Sun15 = 17
)
sum(temps < 18)
[1] 2
sum(temps > 26)
[1] 5
sum(temps <= 21)
[1] 6
sum(temps >= 28)
[1] 4

The which() function

  • The which() function returns the indices of TRUE values.

💻 Hands-On

Consider the following vector

x <- c(-2, -1, 0, 1, 2, 3)

Try the following R code and see what it returns.

which(x < 0)

which(x > 0)
 
which(x <= 0)
 
which(x >= 0)

which(x == 0)

which(x != 0)
which(x < 0)
[1] 1 2
which(x > 0)
[1] 4 5 6
which(x <= 0)
[1] 1 2 3
which(x >= 0)
[1] 3 4 5 6
which(x == 0)
[1] 3
which(x != 0)
[1] 1 2 4 5 6

Relational operators

  • Relational operators are powerful tools to combine conditional statements.
Relationship Operator Description
& and
| or
! not

💻 Hands-On

Consider the following vector

x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)

Try the following R code and see what it returns.

x > 3 & x < 8

!(x > 3 & x < 8)
# 3 < x < 8
x > 3 & x < 8
[1] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE
# Opposite of 3 < x < 8
!(x > 3 & x < 8)
[1]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE

💻 Hands-On

Consider the following vector

x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)

Try the following R code and see what it returns.

x < 4 | x > 6

!(x < 4 | x > 6)
# x < 4 or x > 6
x < 4 | x > 6
[1]  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE
# Opposite of x < 4 or x > 6
!(x < 4 | x > 6)
[1] FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE

💻 Hands-On

Consider daily high temperatures in celsius over two weeks. Write R code to answer the following questions:

  • Which days had temperatures at least 20°C and at most 25°C?

  • Which days had temperatures below 18°C or above 28°C?

# Daily high temperatures over two weeks
temps <- c(
  Mon02 = 18, Tue03 = 21, Wed04 = 19, Thu05 = 25, Fri06 = 27, Sat07 = 30, Sun08 = 22, 
  Mon09 = 20, Tue10 = 16, Wed11 = 24, Thu12 = 28, Fri13 = 31, Sat14 = 29, Sun15 = 17
)
which(temps >= 20 & temps <= 25)
Tue03 Thu05 Sun08 Mon09 Wed11 
    2     4     7     8    10 
which(temps < 18 | temps > 28)
Sat07 Tue10 Fri13 Sat14 Sun15 
    6     9    12    13    14 

Subsetting

  • Certain elements of a vector can be subsetted using the brackets []

  • Subsetting can be done using one of the following indexing methods:

    • Numeric indexing

    • Logical indexing

    • Character indexing (if the vector has names; not covered here)

Numeric indexing

  • Numeric indexing means telling R the specific indices to return values.

  • Consider the following vector

#       1   2   3   4   5   6   7
v <- c(70, 66, 82, 85, 78, 90, 73)
  • We have
# 1st value
v[1]            
[1] 70
# 4th value
v[4]            
[1] 85
# last value, 7th value
v[length(v)]    
[1] 73
# Not available
v[320]          
[1] NA
  • Numeric indexing can also use a vector of multiple indices.
# at 2nd, 3rd, 4th, 5th
v[2:5]                 
[1] 66 82 85 78
# at 5th, 4th, 3rd, 2nd
v[5:2]                 
[1] 78 85 82 66
# at 3rd, 1st, 3rd, 5th, 2nd
v[c(3, 1, 3, 5, 2)]    
[1] 82 70 82 78 66
  • Note that negative indices mean all but the specified indices.
# all but 1st value
v[-1]                    
[1] 66 82 85 78 90 73
# all but 2nd and 5th values
v[-c(2, 5)]              
[1] 70 82 85 90 73
# all but 1st to 4th values
v[-(1:4)]                
[1] 78 90 73
# error!
v[-1:4]                  
Error in v[-1:4]: only 0's may be mixed with negative subscripts

💻 Hands-On

Consider the following vector

#       1   2   3   4   5   6   7
v <- c(70, 66, 82, 85, 78, 90, 73)

Write R code to return the following in v

  • The second value

  • The sixth value

  • The first and last values.

  • The values at positions 3 through 6

  • The values at positions 6 through 3

  • The values at positions 1, 4, and 7

  • All values except the first.

  • All values except the last two.

  • All values except positions 2 and 6.

v[2]
[1] 66
v[6]
[1] 90
v[c(1, length(v))]
[1] 70 73
v[3:6]
[1] 82 85 78 90
v[6:3]
[1] 90 78 85 82
v[c(1, 4, 7)]
[1] 70 85 73
v[-1]
[1] 66 82 85 78 90 73
v[-(6:7)]    # or v[-c(6, 7)]
[1] 70 66 82 85 78
v[-c(2, 6)]
[1] 70 82 85 78 73

Logical Indexing

  • Logical indexing means telling R which values to return and which values not to return.

  • With logical indexing, TRUE will retain the elements, while FALSE will discard the elements.

  • Logical indexing is powerful because it allows for subsetting with conditions.

  • Consider the following vector

#       1   2   3   4   5   6   7
v <- c(70, 66, 82, 85, 78, 90, 73)
# 1st, 6th
v[c(TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE)]    
[1] 70 90
# 2nd, 3rd, 4th
v[c(FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE)]     
[1] 66 82 85
# those values greater than 80
v[v > 80]    
[1] 82 85 90

💻 Hands-On

Consider the following vector

#       1   2   3   4   5   6   7
v <- c(70, 66, 82, 85, 78, 90, 73)

Use numeric and logical indexing to subset

  • 66 82 90 73

  • 70 66 78 73

# 66 82 90 73

v[c(2, 3, 6, 7)]
v[c(FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE)]

# 70 66 78 73

v[c(1, 2, 5, 7)]
v[c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE)]
v[v < 80]

💻 Hands-On

The monthly cost for a stand-alone drug plan varies from plan to plan and from state to state. The vector cost gives the premium for the plan with the lowest cost for each state in 2005 (excludes District of Columbia). Write R code using cost and state.name to find state(s) with a monthly premium

  • Less than or equal to \(\$5\)

  • Greater than \(\$10\)

  • Between \(\$5\) and \(\$10\) (exclusive)

  • Exactly equal to \(\$1.87\)

  • At most \(\$7\)

  • At least \(\$15\)

  • To be the smallest

  • To be the largest

# Recall the vector `state.name`

cost <- c(
  14.08, 20.05, 6.14, 10.31, 5.41, 8.62, 7.32,
  6.44, 10.35, 17.91, 17.18, 6.33, 13.32, 12.30, 1.87,
  9.48, 12.30, 17.06, 19.60, 6.44, 7.32, 13.75, 1.87,
  11.60, 10.29, 1.87, 1.87, 6.42, 19.60, 4.43, 10.65,
  4.10, 13.27, 1.87, 14.43, 10.07, 6.93, 10.14, 7.32,
  16.57, 1.87, 14.08, 10.31, 6.33, 7.32, 8.81, 6.93,
  10.14, 11.42, 1.87
)
state.name[cost <= 5]
[1] "Iowa"         "Minnesota"    "Montana"      "Nebraska"     "New Jersey"  
[6] "New York"     "North Dakota" "South Dakota" "Wyoming"     
state.name[cost > 10]
 [1] "Alabama"        "Alaska"         "Arkansas"       "Florida"       
 [5] "Georgia"        "Hawaii"         "Illinois"       "Indiana"       
 [9] "Kentucky"       "Louisiana"      "Maine"          "Michigan"      
[13] "Mississippi"    "Missouri"       "New Hampshire"  "New Mexico"    
[17] "North Carolina" "Ohio"           "Oklahoma"       "Pennsylvania"  
[21] "South Carolina" "Tennessee"      "Texas"          "West Virginia" 
[25] "Wisconsin"     
state.name[cost > 5 & cost < 10]
 [1] "Arizona"       "California"    "Colorado"      "Connecticut"  
 [5] "Delaware"      "Idaho"         "Kansas"        "Maryland"     
 [9] "Massachusetts" "Nevada"        "Oregon"        "Rhode Island" 
[13] "Utah"          "Vermont"       "Virginia"      "Washington"   
state.name[cost == 1.87]
[1] "Iowa"         "Minnesota"    "Montana"      "Nebraska"     "North Dakota"
[6] "South Dakota" "Wyoming"     
state.name[cost <= 7]
 [1] "Arizona"      "California"   "Delaware"     "Idaho"        "Iowa"        
 [6] "Maryland"     "Minnesota"    "Montana"      "Nebraska"     "Nevada"      
[11] "New Jersey"   "New York"     "North Dakota" "Oregon"       "South Dakota"
[16] "Utah"         "Washington"   "Wyoming"     
state.name[cost >= 15]
[1] "Alaska"         "Georgia"        "Hawaii"         "Louisiana"     
[5] "Maine"          "New Hampshire"  "South Carolina"
state.name[cost == min(cost)]
[1] "Iowa"         "Minnesota"    "Montana"      "Nebraska"     "North Dakota"
[6] "South Dakota" "Wyoming"     
state.name[cost == max(cost)]
[1] "Alaska"

Useful functions for vectors

Given a vector,

  • head() returns its first few elements

  • tail() returns its last few elements

  • sort() returns its sorted version in increasing or decreasing order

  • order() returns the indices of its sorted version

  • rev() returns the reversed vector

  • unique() returns a vector of its unique elements

  • table() shows unique elements and their frequencies

💻 Hands-On

The monthly cost for a stand-alone drug plan varies from plan to plan and from state to state. The vector cost gives the premium for the plan with the lowest cost for each state in 2005 (excludes District of Columbia).

cost <- c(
  14.08, 20.05, 6.14, 10.31, 5.41, 8.62, 7.32,
  6.44, 10.35, 17.91, 17.18, 6.33, 13.32, 12.30, 1.87,
  9.48, 12.30, 17.06, 19.60, 6.44, 7.32, 13.75, 1.87,
  11.60, 10.29, 1.87, 1.87, 6.42, 19.60, 4.43, 10.65,
  4.10, 13.27, 1.87, 14.43, 10.07, 6.93, 10.14, 7.32,
  16.57, 1.87, 14.08, 10.31, 6.33, 7.32, 8.81, 6.93,
  10.14, 11.42, 1.87
)

Try the following R code and see what it returns.

head(cost)    # head(cost, n = 6)

tail(cost)    # tail(cost, n = 6)

sort(cost)

sort(cost, decreasing = TRUE)

order(cost)

order(cost, decreasing = TRUE)

rev(cost)
head(cost)    # head(cost, n = 6)
[1] 14.08 20.05  6.14 10.31  5.41  8.62
tail(cost)    # tail(cost, n = 6)
[1]  7.32  8.81  6.93 10.14 11.42  1.87
sort(cost)
 [1]  1.87  1.87  1.87  1.87  1.87  1.87  1.87  4.10  4.43  5.41  6.14  6.33
[13]  6.33  6.42  6.44  6.44  6.93  6.93  7.32  7.32  7.32  7.32  8.62  8.81
[25]  9.48 10.07 10.14 10.14 10.29 10.31 10.31 10.35 10.65 11.42 11.60 12.30
[37] 12.30 13.27 13.32 13.75 14.08 14.08 14.43 16.57 17.06 17.18 17.91 19.60
[49] 19.60 20.05
sort(cost, decreasing = TRUE)
 [1] 20.05 19.60 19.60 17.91 17.18 17.06 16.57 14.43 14.08 14.08 13.75 13.32
[13] 13.27 12.30 12.30 11.60 11.42 10.65 10.35 10.31 10.31 10.29 10.14 10.14
[25] 10.07  9.48  8.81  8.62  7.32  7.32  7.32  7.32  6.93  6.93  6.44  6.44
[37]  6.42  6.33  6.33  6.14  5.41  4.43  4.10  1.87  1.87  1.87  1.87  1.87
[49]  1.87  1.87
order(cost)
 [1] 15 23 26 27 34 41 50 32 30  5  3 12 44 28  8 20 37 47  7 21 39 45  6 46 16
[26] 36 38 48 25  4 43  9 31 49 24 14 17 33 13 22  1 42 35 40 18 11 10 19 29  2
order(cost, decreasing = TRUE)
 [1]  2 19 29 10 11 18 40 35  1 42 22 13 33 14 17 24 49 31  9  4 43 25 38 48 36
[26] 16 46  6  7 21 39 45 37 47  8 20 28 12 44  3  5 30 32 15 23 26 27 34 41 50
rev(cost)
 [1]  1.87 11.42 10.14  6.93  8.81  7.32  6.33 10.31 14.08  1.87 16.57  7.32
[13] 10.14  6.93 10.07 14.43  1.87 13.27  4.10 10.65  4.43 19.60  6.42  1.87
[25]  1.87 10.29 11.60  1.87 13.75  7.32  6.44 19.60 17.06 12.30  9.48  1.87
[37] 12.30 13.32  6.33 17.18 17.91 10.35  6.44  7.32  8.62  5.41 10.31  6.14
[49] 20.05 14.08

💻 Hands-On

The vectors scores and grades contain exam scores and the corresponding letter grades for students in a statistics class.

scores <- c(
  88, 92, 75, 84, 91, 67, 73, 88, 95, 78,
  82, 90, 69, 74, 85, 88, 93, 77, 81, 89,
  94, 72, 68, 86, 80, 76, 83, 88, 91, 79
)

grades <- c(
  'B', 'A', 'C', 'B', 'A', 'D', 'C', 'B', 'A', 'C',
  'B', 'A', 'D', 'C', 'B', 'B', 'A', 'C', 'B', 'B',
  'A', 'C', 'D', 'B', 'B', 'C', 'B', 'B', 'A', 'C'
)

Write R code to:

  • Show the first and last few exam scores

  • Sort the exam scores in decreasing order

  • Show unique letter grades of students in this class and their frequencies

head(scores)
[1] 88 92 75 84 91 67
tail(scores)
[1] 80 76 83 88 91 79
sort(scores, decreasing = TRUE)
 [1] 95 94 93 92 91 91 90 89 88 88 88 88 86 85 84 83 82 81 80 79 78 77 76 75 74
[26] 73 72 69 68 67
table(grades)
grades
 A  B  C  D 
 7 12  8  3